// 推送验签盐
const JINR_REQUEST_SECRET = '4af1dd714f7397a108b503e93b6f59fe'
const jwt = require('jsonwebtoken'); // 生成token
const ms = require('ms');
const md5 = require('md5');
const moment = require('moment');
const crypto = require('crypto');
// const md5 = crypto.createHash('md5');
//请求发送体验金|现金卷|体验金交易号前缀
const REQUEST_SERIAL_API_NO_PRE = 'serial_';

module.exports = {
  /**
   * 字段非空校验
   * @param {*} data
   */
  isNullFiled(data) {
    let {
      ctx
    } = this
    for (let key in data) {
      if (!data[key]) {
        ctx.body = {
          code: 10001,
          msg: `${key}不能为空`
        }
        ctx.logger.info(`参数校验失败，${key}不能为空`)
        return false
      }
    }
    return true
  },
  /**
   * 验签
   * @param {*} str  要加密的字符串
   * @param {*} sign
   */
  checkSign(str, sign) {
    console.log(md5(str).toLocaleUpperCase(), '------str--------')
    return sign === md5(str).toLocaleUpperCase()
  },
  /**
   * 判断互动是否结束
   * @param {*} startTime
   * @param {*} endTime
   */
  isEnd(startTime, endTime) {
    try {
      console.log(startTime, endTime, 'error')
      let _startTime = new Date(startTime).getTime();
      let _endTime = new Date(endTime).getTime();
      if (!_startTime || !_endTime) {
        this.ctx.logger.info(`传入时间格式有误，startTime=>${startTime},endTime=>${endTime}`);
        return false
      }
      let currentTime = Date.now();
      return _startTime < currentTime && currentTime < _endTime
    } catch (error) {
      console.log(error, 'error')
      this.ctx.logger.error(`判断是否结束报错=>${error}`)
      return false
    }

  },


  /**
   * 生成发送平台奖品序列号
   */
  async sendPrizeRequestNo() {
    let {
      app,
      service,
      ctx
    } = this;
    /**
     * 请求发送体验金|现金卷|体验金交易号前缀
     */
    let requestNoKey = app.config.redisKey.sendPrizeRequestNo
    let id = '';
    if (!await app.redis.exists(requestNoKey)) {
      let requestLog = await service.common.findOne(`
      SELECT id
      FROM hd_api_request_log
      ORDER BY id DESC
      LIMIT 1`);
      id = parseInt(requestLog.id) + 1;
      id ? await app.redis.set(requestNoKey, id) : '';
    } else {
      id = await app.redis.incr(requestNoKey);
    }
    id = id ? id : Math.random().toString(32);
    let request_No = `${REQUEST_SERIAL_API_NO_PRE}${moment(Date.now()).format('YYYYMMDDHHmmss')}${ctx.helper.fillZero(id, 9)}`
    // console.log(request_No,'request_No')
    return request_No

  },
  /**
   *
   * @param {*} data
   * @param {*} num
   */
  fillZero(data, num) {
    data = String(data);
    if (data.length >= num) {
      return data
    } else {
      let temp = data
      for (let i = 0; i < num - data.length; i++) {
        temp = 0 + temp
      }
      return temp
    }
  },
  /**
   *
   * @param {*} data 要加密的数据
   *
   */
  async getToken(data) {
    const {
      ctx,
      app
    } = this;
    let created = Math.floor(Date.now() / 1000);
    let cert = app.config.jwtConfig.cert; //私钥
    let time = app.config.jwtConfig.exp;
    let token = jwt.sign({
      data,
      exp: created + time
      // exp: created + 60
    }, cert); //默认使用SHA256
    // 将token设置到cookie中
    ctx.helper.cookieSet('token', token);
    // 将token存储到redis中
    // console.log('20tian 00000000', ms('2days'))
    let redisKey = `${app.config.redisKey.adminToken}:${data.userId}`;
    await app.redis.setex(redisKey, ms('2days'), token); // 保存时间为两天
    return token;
  },
  /**
   *
   * @param  {*} token // 验证token
   * @return {*} res.state  1验证通过| 2登录过期 | 3 账号在其他地方登录 | 4token验证失败
   */
  async verifyToken(token) {
    const {
      app,
      ctx,
      logger
    } = this;
    let res = {};
    // console.log('进入验证');
    if (!token) {
      return {
        state: 0
      }
    }
    logger.info(`用户token==>${token}`)
    let cert = app.config.jwtConfig.cert; //私钥
    try {
      let result = jwt.verify(token, cert) || {};
      console.log(result, 'result------result');
      // let {
      //   exp = 0
      // } = result, current = Math.floor(Date.now() / 1000);

      let userId = result.data.userId;
      let redisKey = `${app.config.redisKey.adminToken}:${userId}`;
      let _token = await app.redis.get(redisKey);
      let _regisResult = jwt.verify(_token, cert) || {};
      console.log('_token', redisKey, result.iat, _regisResult.iat)
      if (result.iat !== _regisResult.iat) { //账号在其他地方登录
        return {
          state: 3
        }
      }
      res.data = result.data || {};
      res.state = 1;
      let current = Date.now() / 1000;
      console.log(result.exp - current, ms('2h') / 1000, '过期时间--------')
      if (result.exp - current < (ms('2h') / 1000)) { // 距离过期时间还有2小时时重新设置token
        console.log('重新设置过期时间')
        await ctx.helper.getToken(result.data)
      }
    } catch (error) {
      console.log(error);
      if (error.name === 'TokenExpiredError') {
        res.state = 2
      } else {
        res.state = 4
      }
    }
    return res;
  },

  /**
   * 加密
   * @param  {*} token // 验证token
   */
  aesEncrypt({
    data,
    salt,
    type
  }) {
    // const crypto = require('crypto');
    const hmac = crypto.createHash(`${type || 'md5'}`);
    const {
      app,
      ctx,
      logger
    } = this, baseSalt = app.config.salts;
    let randomSalt = '';
    if (!salt) { // 没有盐
      for (let i = 0; i < 6; i++) {
        randomSalt += baseSalt[Math.floor(Math.random() * baseSalt.length)];
      }
      salt = randomSalt;
    }
    data = `${data}:${salt}`;
    logger.info(`加密前=>${data}`);
    hmac.update(data);
    // let encryData = hmac.digest('hex');
    return {
      salt,
      encryData: hmac.digest('hex')
    }

  },

  encryptCb(combination) {
    const { app, ctx } = this;
    let key = app.config.combinationSalt;
    // const crypto = require('crypto');
    const cipher = crypto.createCipher('aes192', key);

    let encrypted = cipher.update(String(combination), 'utf8', 'hex');
    encrypted += cipher.final('hex');
    return encrypted
    // console.log(encrypted,'---------')

  },



  cookieSet(key, value, time) {
    let {
      ctx
    } = this;
    ctx.cookies.set(key, value, {
      maxAge: time || ms('10days'), //cookie有效期10天
      encrypt: true, // 加密传输
    });
  },
  cookieGet(key) {
    let {
      ctx
    } = this;
    return ctx.cookies.get(key, {
      encrypt: true, // 加密传输
    });
  },
  /**
   * sql格式化
   * @param  {*} obj     要格式化的对象
   * @param  {*} type    格式化的类型
   */
  sqlFormData(obj, type) {
    // if (type == 'where') {
    let temp = [];
    let whereType = null
    if (obj.whereType) {
      whereType = obj.whereType
      delete obj.whereType;
    }
    console.log(typeof obj === 'string', !(obj instanceof Object), 'temp-------temp')
    if (!(obj instanceof Object) && typeof obj === 'string' && type) {
      // console.log('xxxxx--------进来了')
      return `${type} ${obj}`
    }
    for (let key in obj) {
      temp.push(`${key}=${obj[key]}`)
    }
    if (type == 'where') {
      return whereType ? ` WHERE ${temp.join(` OR `)}` : ` WHERE ${temp.join(` AND `)}`
    } else if (type == 'SET') { // 更新
      return `SET ${temp.join(',')}`
    }
  },
  /**
   * 路由格式化
   */
  formDataRouter(baseRouter, router) {
    // console.log(router,'router---------')
    let {
      ctx
    } = this;
    if (!router) {
      router = baseRouter['0'];
    }
    for (let item of router) {
      if (baseRouter[item.id]) {
        item.children = baseRouter[item.id]
        ctx.helper.formDataRouter(baseRouter, baseRouter[item.id])
      }
    }
    return router
  },


  /**
 * 生成渠道/活动key
 * @param $id   id
 * @param $startTime  开始时间
 * @param type  首字符
 */
  getEventKey(id, startTime, type) {
    const { ctx } = this;
    id = id.toString()
    // console.log('--moment--', moment().format('YYMMDD'))
    let channelSerial = !!startTime ? type + moment(startTime).format('YYMMDD') : type + moment().format('YYMMDD')
    id = id.length <= 4 ? ctx.helper.strPad(id, 4, '0') : id
    channelSerial += id
    return channelSerial
  },


  /**
   *
   * @param {渠道id}
   * @param {长度} len
   * @param {补位字符} str
   */
  strPad(id, len, str) {
    let strLen = String(id).length
    let padLen = len - strLen
    for (let i = 0; i < padLen; i++) {
      id += str
    }
    return id.split("").reverse().join("")
  },

  formDate(date, str) {
    return moment(date).format(str);
  }

}